package py.com.alfa.escriba.gui.controller;

import java.io.Serializable;
import java.util.Locale;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.thymeleaf.TemplateEngine;
import org.winter.dialect.response.JsonResponse;
import org.winter.utils.command.ControllerObject;

import py.com.alfa.escriba.gui.controller.object.referencia.BarriosControllerObject;
import py.com.alfa.escriba.gui.controller.view.View;
import py.com.alfa.escriba.gui.controller.view.ViewManager;
import py.com.alfa.escriba.gui.dto.admin.BarrioDTO;
import py.com.alfa.escriba.gui.rest.services.ReferenciaService;
import py.com.alfa.escriba.gui.session.SystemInfo;
import py.com.alfa.escriba.gui.spring.processors.SpringBean;
import py.com.sif.rest.client.spring.exception.RestClientException;

@Controller
@Scope("session")
@SessionAttributes("barrios")
@RequestMapping("/barrios")
public class BarriosController implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 4845167048299228510L;
	private final static String PAGE_NAME = "pag:localidades";
	private final static String CONTROLLER_OBJECT_NAME = "barrios";
	
	private Logger log = LoggerFactory.getLogger(getClass());
	@SpringBean private ReferenciaService referenciaService;
	@SpringBean private SystemInfo systemInfo;
	@SpringBean private ViewManager viewManager;
	@Autowired
	private ServletContext servletContext;
	@Autowired
	private TemplateEngine templateEngine;
	@ControllerObject
	private BarriosControllerObject barrios;	
	private Locale locale;
	
	public BarriosController() {
		this.loadObjects();
	}

	private void loadObjects() {
		setLocale(LocaleContextHolder.getLocale());
	}

	private String verifAuto() {
		Subject subject = SecurityUtils.getSubject();
		if (subject == null || !subject.isAuthenticated()) {
			return "redirect:/";
		}		
		Boolean permitted = subject.isPermitted(BarriosController.PAGE_NAME);
		systemInfo.setSystemError(false);
		if (!permitted) {
			systemInfo.setSystemError(true);
			systemInfo.setErrorMessage("El usuario no esta autorizado para utilizar este recurso");
			return "error";
		}
		return null;
	}
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	public String homePage(Model model, HttpServletRequest request, HttpServletResponse response,@PathVariable("id") String id) {
		this.log.debug("barrios! {}", id);
		try {
			this.getBarrios().view().disable().localidades();
			String auto = this.verifAuto();
			if ( auto != null ) {
				return auto;
			}
			if ( id == null ) {
				systemInfo.setSystemError(true);
				systemInfo.setErrorMessage("Error al entrar en la pagina de barrios");
				return "error";				
			}
			Long idDistrito = Long.parseLong(id);
			this.getBarrios().setDistrito(this.referenciaService.obtenerDistrito(idDistrito));
			if ( this.getBarrios().getDistrito() == null ) {
				systemInfo.setSystemError(true);
				systemInfo.setErrorMessage("No existe el distrito, verifique");
				return "error";								
			}
			this.getBarrios().setBarrios(this.referenciaService.obtenerBarrios(idDistrito));
			this.getBarrios().view().enable().localidades();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
		}
		return View.BARRIOS;
	}
	
	@RequestMapping(value = "/crear", method = RequestMethod.POST)
	public @ResponseBody JsonResponse crear(Model model,HttpServletRequest request,HttpServletResponse response,
			                                @ModelAttribute(CONTROLLER_OBJECT_NAME) BarriosControllerObject controllerObject,
			                                BindingResult bindingResult) {
		this.log.info("\n==============\nCREANDO!\n==============\n");
		JsonResponse jresponse = JsonResponse.getInstance(View.BARRIOS);
		WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		try {
			this.log.info("\n==============\nBARRIOS : {} - {}!\n==============\n",controllerObject.getBarrio());
			
			this.referenciaService.crearBarrio(controllerObject.getBarrio());
			this.getBarrios().getBarrios().add(controllerObject.getBarrio());
			controllerObject.setBarrio(null);
			this.setBarrios(controllerObject);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jresponse.error(e.getCause().getMessage());
			}
		}
		model.addAttribute(CONTROLLER_OBJECT_NAME, this.getBarrios());
		return jresponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/nuevoBarrio", method = RequestMethod.POST)
	public @ResponseBody JsonResponse nuevo(Model model,HttpServletRequest request,HttpServletResponse response,
			                                @ModelAttribute(CONTROLLER_OBJECT_NAME) BarriosControllerObject controllerObject,
			                                BindingResult bindingResult) {
		this.log.info("\n==============\nNUEVO!\n==============\n");
		JsonResponse jresponse = JsonResponse.getInstance(View.BARRIOS);
		WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		try {
			this.getBarrios().setBarrio(null);
			//this.getBarrios().getBarrio().setIdDepartamento(this.getBarrios().getDistrito().getIdDepartamento());
			this.getBarrios().getBarrio().setIdDistrito(this.getBarrios().getDistrito().getId());
			this.getBarrios().view().enable().nuevo().disable().editar();
			this.setBarrios(controllerObject);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jresponse.error(e.getCause().getMessage());
			}
		}
		model.addAttribute(CONTROLLER_OBJECT_NAME, this.getBarrios());
		return jresponse.success(request, response, wac, model, templateEngine);
	}

	@RequestMapping(value = "/eliminar/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse eliminar(Model model,HttpServletRequest request, HttpServletResponse response, @PathVariable("index") String ind) {
		this.log.info("\n==============\nELIMINANDO! {}\n==============\n", ind);
		JsonResponse jresponse = JsonResponse.getInstance(View.BARRIOS);
		WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		try {
			Integer index = Integer.parseInt(ind);
			BarrioDTO obj = this.getBarrios().getBarrios().get(index);
			this.log.info("Distrito: {}", obj);
			
			this.referenciaService.eliminarBarrio(obj.getId());
            this.getBarrios().getBarrios().remove(obj);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jresponse.error(e.getCause().getMessage());
			}
		}
		model.addAttribute(CONTROLLER_OBJECT_NAME, this.getBarrios());
		return jresponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/editar/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse editar(Model model, HttpServletRequest request, HttpServletResponse response,
			                                 @PathVariable("index") String ind) {
		this.log.info("\n==============\nEDITANDO! BARRIOS\n==============\n");
		JsonResponse jresponse = JsonResponse.getInstance(View.BARRIOS);
		WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		try {
			Integer index = Integer.parseInt(ind);
			BarrioDTO obj = this.getBarrios().getBarrios().get(index);
			this.getBarrios().setBarrio(obj);
			this.getBarrios().view().disable().nuevo().enable().editar();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jresponse.error(e.getCause().getMessage());
			}
		}
		model.addAttribute(CONTROLLER_OBJECT_NAME, this.getBarrios());
		return jresponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/actualizar", method = RequestMethod.POST)
	public @ResponseBody JsonResponse guardarEdicion(Model model, HttpServletRequest request, HttpServletResponse response,
			                                         @ModelAttribute(CONTROLLER_OBJECT_NAME) BarriosControllerObject controllerObject,
			                                         BindingResult bindingResult) {
		this.log.info("\n==============\nEDITANDO BARRIOS!\n==============\n");
		JsonResponse jresponse = JsonResponse.getInstance(View.BARRIOS);
		WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		try {
			this.log.info("\n==============\nBARRIOS: {}!\n==============\n", controllerObject.getBarrio());
			this.referenciaService.actualizarBarrio(controllerObject.getBarrio());
			controllerObject.setBarrio(null);
			this.getBarrios().view().disable().nuevo().disable().editar();
			this.setBarrios(controllerObject);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jresponse.error(e.getCause().getMessage());
			}
		}
		model.addAttribute(CONTROLLER_OBJECT_NAME, this.getBarrios());
		return jresponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/cancelar", method = RequestMethod.POST)
	public @ResponseBody JsonResponse cancelar(Model model, HttpServletRequest request, HttpServletResponse response,
                                               @ModelAttribute(CONTROLLER_OBJECT_NAME) BarriosControllerObject controllerObject, BindingResult bindingResult) {
		this.log.info("\n==============\nCancelar!\n==============\n");
		JsonResponse jresponse = JsonResponse.getInstance(View.BARRIOS);
		WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		try {
			controllerObject.setBarrio(null);
			this.getBarrios().view().disable().nuevo().disable().editar();
			this.setBarrios(controllerObject);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jresponse.error(e.getCause().getMessage());
			}
		}
		model.addAttribute(CONTROLLER_OBJECT_NAME, this.getBarrios());
		return jresponse.success(request, response, wac, model, templateEngine);
	}	
	@ModelAttribute(CONTROLLER_OBJECT_NAME)
	public BarriosControllerObject getBarrios() {
		return this.barrios;
	}
	
	public void setBarrios(BarriosControllerObject listas) {
		this.barrios = listas;
	}

	public Locale getLocale() {
		return locale;
	}

	public void setLocale(Locale locale) {
		this.locale = locale;
	}	
}
